package org.openfans.web;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.openfans.domain.Article;
import org.openfans.domain.Comment;
import org.openfans.domain.Facade;
import org.openfans.domain.Fans;
import org.openfans.domain.Feed;
import org.openfans.domain.FeedItem;
import org.openfans.domain.Group;
import org.openfans.domain.Page;
import org.openfans.domain.PreFans;
import org.openfans.domain.RootTag;
import org.openfans.domain.Tag;
import org.openfans.domain.UseStatus;
import org.openfans.util.ThreadFans;
import org.openfans.web.clickstream.OpenfansClickstream;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

/**
 * Desc：User MultiActionController to handle all View or List task<br>
 * Date：2007-1-22<br>
 * 
 * @author pesome<br>
 * @email:pesome@gmail.com<br>
 */
public class ViewController extends MultiActionController {
	private int articlePageSize;

	private Facade facade = null;

	private int fansPageSize;

	private int feedItemPageSize;

	private int rootTagPageSize;

	private int feedPageSize;

	private int tagPageSize;

	private int messagePageSize;

	/**
	 * 功能说明：区分几种statusSet，并放入model map�?<br>
	 * 创建者：张俊<br>
	 * 创建时间�?2006-2-25<br>
	 * 
	 * @param set
	 * @param map
	 */
	private void divideStatusSet(Set<UseStatus> set, Map<String, Object> map) {
		map.put("used", getStatusSet(UseStatus.USED, set));
		map.put("using", getStatusSet(UseStatus.USING, set));
		map.put("prepare", getStatusSet(UseStatus.PREPARE, set));
	}

	private String getArticleOrderFromReq(HttpServletRequest request) {
		return Article.getOrder(getOrderIntFromReq(request));
	}

	private String getFansOrderFromReq(HttpServletRequest request) {
		return Fans.getOrder(getOrderIntFromReq(request));
	}

	/**
	 * 功能说明：所有需要排序的地方，从request获取排序�?<br>
	 * 创建者：张俊<br>
	 * 创建时间�?2006-5-12<br>
	 * 
	 * @param request
	 * @return
	 */
	private int getOrderIntFromReq(HttpServletRequest request) {
		String order = request.getParameter("o");
		int orderInt = 0;
		if (order != null && !"".equals(order.trim())) {
			orderInt = Integer.parseInt(order);
		}
		return orderInt;
	}

	/**
	 * �?有需要过滤的地方，从request获取过滤�?
	 * 
	 * @param request
	 * @return
	 */
	private int getConditionIntFromReq(HttpServletRequest request) {
		String condition = request.getParameter("c");
		int conditionInt = 0;
		if (condition != null && !"".equals(condition.trim())) {
			conditionInt = Integer.parseInt(condition);
		}
		return conditionInt;
	}

	private int getPageNum(HttpServletRequest request) {
		int pageNum = 1;
		String page = request.getParameter("page");
		if (page != null && page.trim().length() != 0) {
			pageNum = Integer.parseInt(page);
		}
		return pageNum;
	}

	/**
	 * 功能说明：从statusSet中取出特定状态的set<br>
	 * 创建者：张俊<br>
	 * 创建时间�?2006-2-25<br>
	 * 
	 * @param i
	 * @param set
	 * @return
	 */
	private Set getStatusSet(int i, Set<UseStatus> set) {
		Set<UseStatus> ss = new HashSet<UseStatus>();
		for (UseStatus us : set) {
			if (us.getStatus() == i) {
				ss.add(us);
			}
		}
		return ss;
	}

	private String getTagOrderFromReq(HttpServletRequest request) {
		return Tag.getOrder(getOrderIntFromReq(request));
	}

	private void hasNextAndPre(int pageNum, int size, List l,
			Map<String, Object> map) {
		if (pageNum > 1) {
			map.put("pre", String.valueOf(pageNum - 1));
		}
		// �?化分页，不count总数，会有一点小问题�?
		// 就是恰好到这页的�?后一个是全部的结束时，会出现空的下一�?
		if (l.size() == size) {
			map.put("next", String.valueOf(pageNum + 1));
		}
	}

	public ModelAndView listArticle(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);
		String type = request.getParameter("type");
		String title = request.getParameter("title");
		String order = getArticleOrderFromReq(request);
		Page page = facade.searchArticles(title, order, type, pageNum,
				articlePageSize);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		map.put("type", type);
		map.put("title", title);
		putOrderToMap(request, map);
		return new ModelAndView("public/listArticle", map);
	}

	public ModelAndView listSavedArticle(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);

		// String type = request.getParameter("type");
		String tag = request.getParameter("tag");

		String order = "article_id desc";
		Page page = facade.searchFansSavedArticles(
				ThreadFans.get().getFansId(), tag, pageNum, articlePageSize,
				order);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("tag", tag);
		map.put("page", page);
		putOrderToMap(request, map);
		// hasNextAndPre(pageNum, articlePageSize, l, map);
		return new ModelAndView("ajax/listSavedArticle", map);
	}

	public ModelAndView listFansSnippet(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);

		// String type = request.getParameter("type");
		String tag = request.getParameter("tag");
		String size = request.getParameter("size");
		int pageSize = 10;
		if (null != size && !"".equals(size)) {
			pageSize = Integer.parseInt(size);
		}
		String order = "id desc";
		Page page = facade.getPagedFansSnippet(ThreadFans.get(), tag, order,
				pageNum, pageSize);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("tag", tag);
		map.put("page", page);
		// putOrderToMap(request, map);
		// hasNextAndPre(pageNum, articlePageSize, l, map);
		return new ModelAndView("ajax/listFansSnippet", map);
	}

	public ModelAndView listSnippet(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);

		// String type = request.getParameter("type");
		String tag = request.getParameter("tag");
		String size = request.getParameter("size");
		int pageSize = 10;
		if (null != size && !"".equals(size)) {
			pageSize = Integer.parseInt(size);
		}
		String order = "id desc";
		Page page = facade.getPagedSnippet(tag, order, pageNum, pageSize);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("tag", tag);
		map.put("page", page);
		// putOrderToMap(request, map);
		// hasNextAndPre(pageNum, articlePageSize, l, map);
		return new ModelAndView("public/snippet/listSnippet", map);
	}

	public ModelAndView myFavorite(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		ThreadFans.authorize();
		return new ModelAndView("public/myFavorite");
	}

	public ModelAndView mySnippet(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		ThreadFans.authorize();
		return new ModelAndView("public/snippet/mySnippet");
	}

	public ModelAndView listFans(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		int pageNum = getPageNum(request);
		Page page = facade.getPagedFans(pageNum, fansPageSize,
				getFansOrderFromReq(request));
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		putOrderToMap(request, map);
		return new ModelAndView("public/listFans", map);
	}

	/**
	 * 用户查看最新日志列表.游客显示所有日志,用户只显示他订阅过的Feed所产生的日志 Author:pesome<br>
	 * Date:2007-1-22<br>
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView listFeedItem(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		return new ModelAndView("public/listFeedItem");
	}

	/**
	 * 列出用户所提交的Feed产生的日志<br>
	 * Author:pesome<br>
	 * Date:2007-1-22<br>
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView listFansFeedItem(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String name = request.getParameter("name");
		Fans fans = facade.getFans(name);
		int pageNum = getPageNum(request);

		Page page = facade.getPagedFansFeedItems(fans, "id desc", pageNum,
				feedItemPageSize);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		map.put("fans", fans);
		return new ModelAndView("public/listFansFeedItem", map);
	}

	public ModelAndView listTagFeedItem(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String id = request.getParameter("id");
		Tag tag = facade.getTag(Integer.parseInt(id));
		int pageNum = getPageNum(request);

		Page page = facade.getPagedTagFeedItems(tag, "id desc", pageNum,
				feedItemPageSize);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		map.put("tag", tag);
		return new ModelAndView("public/listTagFeedItem", map);
	}

	/**
	 * Get feedItems of Feed
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public ModelAndView listFeedFeedItem(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String id = request.getParameter("id");
		Feed feed;
		Page page;
		int pageNum = getPageNum(request);
		Fans fans = ThreadFans.get();
		// -1代表全部
		if ("-1".equals(id)) {
			if (!(fans instanceof PreFans)) {
				page = facade.getPagedFansSubFeedItems(fans, "id desc",
						pageNum, feedItemPageSize);
			} else {
				page = facade.getPagedFeedItems("id desc", pageNum,
						feedItemPageSize);
			}
		} else {
			feed=facade.getFeed(Integer.parseInt(id));
			page = facade.getPagedFeedFeedItems(feed, "id desc", pageNum,
					feedItemPageSize);
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		map.put("id", id);
		return new ModelAndView("ajax/listFeedFeedItem", map);
	}

	public ModelAndView listGroup(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();
		List l = facade.listGroup();
		map.put("groupList", l);
		return new ModelAndView("public/listGroup", map);
	}

	public ModelAndView listRootTag(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);
		String order = getTagOrderFromReq(request);
		Page page = facade.getPagedRootTags(order, pageNum, rootTagPageSize);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		putOrderToMap(request, map);
		return new ModelAndView("public/listRootTag", map);
	}

	public ModelAndView listFeed(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);
		Page page=facade.getPagedFeed(pageNum, feedPageSize);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		return new ModelAndView("ajax/listFeed", map);
	}

	public ModelAndView listFansSubFeed(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();
		if (!(ThreadFans.get() instanceof PreFans)) {
			Fans fans = facade.getFans(ThreadFans.get().getFansId());
			map.put("subFeedSet", fans.getSubFeedSet());
		}
		return new ModelAndView("ajax/listFansSubFeed", map);
	}

	public ModelAndView listTag(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int pageNum = getPageNum(request);
		// String order = getTagOrderFromReq(request);
		List l = facade.getPagedTags(pageNum, tagPageSize, "title asc");
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("tagList", l);
		putOrderToMap(request, map);
		hasNextAndPre(pageNum, tagPageSize, l, map);
		return new ModelAndView("public/listTag", map);
	}

	public ModelAndView listFansFeed(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Set s = facade.getFans(ThreadFans.get().getFansId()).getFeeds();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("feeds", s);
		return new ModelAndView("ajax/listFansFeed", map);
	}

	public ModelAndView listFansTag(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Set s = facade.getFans(ThreadFans.get().getFansId()).getUsedTagSet();
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("tags", s);
		return new ModelAndView("ajax/listFansTag", map);
	}
	
	public ModelAndView listRootTagRemark(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String id=request.getParameter("id");
		int pageNum = getPageNum(request);
		RootTag tag=(RootTag)facade.getTag(Integer.parseInt(id));
		Page page=facade.getPagedRootTagRemarks(tag, "remark_date desc", pageNum, 20);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("page", page);
		return new ModelAndView("ajax/listRootTagRemark", map);
	}

	public ModelAndView listMessage(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String type = request.getParameter("type");
		int pageNum = getPageNum(request);
		List l = null;
		Fans f = ThreadFans.get();
		if ("post".equals(type)) {
			l = facade.getPagedPostMessages(pageNum, messagePageSize, f
					.getFansId(), "post_date desc");

		} else if ("receive".equals(type)) {
			l = facade.getPagedReceiveMessages(pageNum, messagePageSize, f
					.getFansId(), "post_date desc");
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("messageList", l);
		putOrderToMap(request, map);
		hasNextAndPre(pageNum, messagePageSize, l, map);
		return new ModelAndView("public/listMessage", map);
	}

	private void putOrderToMap(HttpServletRequest request,
			Map<String, Object> map) {
		map.put("o", String.valueOf(getOrderIntFromReq(request)));
	}

	private void putConditionToMap(HttpServletRequest request,
			Map<String, Object> map) {
		map.put("c", String.valueOf(getConditionIntFromReq(request)));
	}

	public ModelAndView searchTag(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String tag = request.getParameter("tag");
		Map<String, Object> map = new HashMap<String, Object>();
		if (tag != null && tag.trim().length() > 0) {
			String title = tag.split(" ")[0];
			List tagList = facade.searchTags(title);
			map.put("tagList", tagList);
		}
		return new ModelAndView("ajax/searchTag", map);
	}

	public void setArticlePageSize(int articlePageSize) {
		this.articlePageSize = articlePageSize;
	}

	public void setFacade(Facade facade) {
		this.facade = facade;
	}

	public void setFansPageSize(int fansPageSize) {
		this.fansPageSize = fansPageSize;
	}

	public void setFeedItemPageSize(int feedItemPageSize) {
		this.feedItemPageSize = feedItemPageSize;
	}

	public void setRootTagPageSize(int rootTagPageSize) {
		this.rootTagPageSize = rootTagPageSize;
	}

	public void setFeedPageSize(int feedPageSize) {
		this.feedPageSize = feedPageSize;
	}

	public void setTagPageSize(int tagPageSize) {
		this.tagPageSize = tagPageSize;
	}

	public ModelAndView viewArticle(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int articleId = Integer.parseInt(request.getParameter("id"));
		Map<String, Object> map = new HashMap<String, Object>();
		Article article = facade.getArticle(articleId);

		// 增加这个article的查看次�?
		Map<String, Object> articleMap = ((OpenfansClickstream) request
				.getSession().getAttribute(
						OpenfansClickstream.SESSION_ATTRIBUTE_KEY))
				.getFansMap();
		Object o = articleMap.put(String.valueOf(article.getArticleId()),
				new Object());
		if (o == null) {// �?个session对一个article的访问只算一�?
			article.addHot(1);
			facade.save(article);
		}

		map.put("article", article);
		map.put("titlePart", article);
		map.put("comment", new Comment());
		map.put("relArticles", facade.getRelArticles(article));
		if (article.getFans().getFansId() == ThreadFans.get().getFansId()) {
			map.put("isAuthor", "true");
		}
		return new ModelAndView("public/viewArticle", map);
	}

	public ModelAndView viewFans(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// int fansId = Integer.parseInt(request.getParameter("id"));
		String name = request.getParameter("name");
		Map<String, Object> map = new HashMap<String, Object>();
		Fans fans = facade.getFans(name);

		// 增加这个fans的查看次�?
		Map<String, Object> fansMap = ((OpenfansClickstream) request
				.getSession().getAttribute(
						OpenfansClickstream.SESSION_ATTRIBUTE_KEY))
				.getFansMap();
		Object o = fansMap.put(String.valueOf(fans.getFansId()), new Object());
		if (o == null) {// �?个session对一个fans的访问只算一�?
			fans.addHot(1);
			facade.saveFans(fans);// 不是用id load，所以不在hibernate中，�?要显式持久化
		}
		map.put("fans", fans);
		map.put("titlePart", fans.getNickName());
		Set<UseStatus> set = fans.getUseStatusSet();
		divideStatusSet(set, map);
		return new ModelAndView("public/viewFans", map);
	}

	public ModelAndView viewFeedItem(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int id = Integer.parseInt(request.getParameter("id"));
		Map<String, Object> map = new HashMap<String, Object>();
		FeedItem feedItem = facade.getFeedItem(id);
		map.put("feedItem", feedItem);
		List relFeedItems = facade.getRelFeedItems(feedItem);
		map.put("relFeedItems", relFeedItems);
		// map.put("comment", new Comment());
		// map.put("relArticles", facade.getRelArticles(article));

		return new ModelAndView("public/viewFeedItem", map);
	}

	public ModelAndView viewGroup(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int groupId = Integer.parseInt(request.getParameter("id"));
		Group group = facade.getGroup(groupId);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("group", group);
		map.put("titlePart", group.getName());
		if (group.containsFans(ThreadFans.get())) {
			map.put("inGroup", new Boolean(true));
		}
		return new ModelAndView("public/viewGroup", map);
	}

	public ModelAndView viewFeed(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		int feedId = Integer.parseInt(request.getParameter("id"));
		Map<String, Object> map = new HashMap<String, Object>();
		Feed feed = facade.getFeed(feedId);
		map.put("feed", feed);
		int pageNum = getPageNum(request);
		Page page = facade.getPagedFeedFeedItems(feed, "id desc", pageNum,
				feedItemPageSize);
		map.put("page", page);
		putConditionToMap(request, map);

		return new ModelAndView("public/viewFeed", map);
	}

	public ModelAndView viewTag(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		Tag tag = null;
		String tagStr = request.getParameter("name");
		if (null != tagStr) {
			// TODO 这里做了转码，但具体代码与服务器的字符集相关
			tagStr = new String(tagStr.getBytes("ISO-8859-1"), "GBK");
			tag = facade.getTagByTitle(tagStr);
		} else {// 要兼顾搜索引擎已有链接，将来可以去掉
			String tagId = request.getParameter("id");
			tag = facade.getTag(Integer.parseInt(tagId));
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("tag", tag);
		// map.put("titlePart", tag.getTitle());
		// 增加这个tag的查看次�?
		Map<String, Object> tagMap = ((OpenfansClickstream) request
				.getSession().getAttribute(
						OpenfansClickstream.SESSION_ATTRIBUTE_KEY)).getTagMap();
		Object o = tagMap.put(String.valueOf(tag.getTagId()), new Object());
		if (o == null) {// �?个session对一个tag的访问只算一�?
			tag.addHot(1);
			facade.save(tag);
		}

		if (tag instanceof RootTag) {
			Set<UseStatus> set = ((RootTag) tag).getUseStatusSet();
			Fans fans = ThreadFans.get();
			if (fans.getFansId() != -1) {
				for (UseStatus us : set) {
					if (fans.getFansId() == us.getFans().getFansId()) {
						map.put("curStatus", us);
						break;
					}
				}
			}
			divideStatusSet(set, map);
			return new ModelAndView("public/viewRootTag", map);
		} else {
			// 获取与一个普通tag关联的roottag列表
			List relRootTagList = facade.getTagRelRootTag(tag);
			map.put("relRootTagList", relRootTagList);
			return new ModelAndView("public/viewTag", map);
		}
	}

	public void setMessagePageSize(int messagePageSize) {
		this.messagePageSize = messagePageSize;
	}
}
